use crate::app::node::NodeUI;
use crate::app::UIComponent;
use crate::config::AppConfig;
use crate::data::{ANode, Node};
use crate::types::{NodePosition, NodeType};
use eframe::egui;
use eframe::egui::scroll_area::{ScrollBarVisibility, ScrollSource};
use eframe::egui::{CentralPanel, Id, Pos2, Rect, Response, Ui, Vec2};
use std::collections::HashMap;
use std::ops::Add;
use std::sync::Arc;

pub struct NodeStruct {}

impl NodeStruct {
    pub fn new() -> NodeStruct {
        NodeStruct {}
    }

    fn add_node(ui: &mut Ui, node: ANode, pos: Pos2, node_position: NodePosition) -> Response {
        let mut map = HashMap::<Id, ANode>::new();
        let config = AppConfig::get(ui.ctx());
        let rect = Rect::from_center_size(pos, config.node_size);
        let response = ui.put(rect, NodeUI::new(Arc::clone(&node), node_position));
        map.insert(response.id, Arc::clone(&node));
        if response.clicked() {
            if let Some(a_curr_node) = map.get(&response.id) {
                Node::set_current_node(ui.ctx(), Arc::clone(a_curr_node));
                if let Ok(curr_node) = a_curr_node.try_lock() {
                    match curr_node.node_type.value {
                        NodeType::Leaf(is_condition) => {
                            if !is_condition {
                                let root_node = Node::get_root_node(ui.ctx());
                                Node::set_list_root_node(ui.ctx(), Arc::clone(&root_node))
                            }
                        }
                        NodeType::Composite(is_root, is_condition) => {
                            if is_root && is_condition {
                                Node::set_list_root_node(ui.ctx(), Arc::clone(a_curr_node))
                            } else if !is_condition {
                                let root_node = Node::get_root_node(ui.ctx());
                                Node::set_list_root_node(ui.ctx(), Arc::clone(&root_node))
                            }
                        }
                    }
                };
            };
        };
        response
    }
}

impl UIComponent for NodeStruct {
    fn update(&mut self, ui: &mut Ui) {
        // 节点树状图
        CentralPanel::default().show_inside(ui, |ui| {
            let shift_pressing = ui.input(|i| {i.modifiers.shift_only()});
            egui::ScrollArea::both()
                .scroll([shift_pressing, !shift_pressing])
                .scroll_source(ScrollSource {drag: true, ..Default::default()})
                .scroll_bar_visibility(ScrollBarVisibility::AlwaysHidden)
                .show(ui, |ui| {
                let node = Node::get_current_node(ui.ctx());
                let (
                    parent_node,
                    relate_node,
                    children,
                    brother,
                ) = Node::get_nodes(&node);

                let config = AppConfig::get(ui.ctx());
                let available_width = ui.available_width();
                let available_height = ui.available_height();
                let pos = ui.next_widget_position().add(Vec2 { x: available_width / 2.0, y: available_height / 4.0 });

                if let Some(relate_node) = relate_node {
                    // 绘制关联条件节点
                    Self::add_node(
                        ui,
                        Arc::clone(&relate_node),
                        pos + Vec2::new(-config.node_spacing.x, 0.0),
                        NodePosition::Relate,
                    );
                };

                // 绘制子节点
                for (i, child_node) in children.iter().enumerate() {
                    Self::add_node(
                        ui,
                        Arc::clone(child_node),
                        pos + Vec2::new(
                            -config.node_spacing.x,
                            config.node_spacing.y * (i + 1) as f32,
                        ),
                        NodePosition::Child,
                    );
                };

                // 绘制兄弟节点
                for (index, brother_node) in brother.into_iter().enumerate() {
                    Self::add_node(
                        ui,
                        Arc::clone(&brother_node),
                        pos + Vec2::new(
                            config.node_spacing.x,
                            config.node_spacing.y * index as f32,
                        ),
                        NodePosition::Brother,
                    );
                };

                // 绘制当前节点
                Self::add_node(ui, Arc::clone(&node), pos, NodePosition::Current);

                // 绘制父节点
                if let Some(parent_node) = parent_node {
                    Self::add_node(
                        ui,
                        Arc::clone(&parent_node),
                        pos + Vec2::new(0., -config.node_spacing.y),
                        NodePosition::Parent,
                    );
                };
            });
        });
    }
}
